local util = require "util"
local skynet = require "skynet"
local cjson = require "cjson"
local constant = require "constant"
local error_code = require "error_code"
local tree_handler = require "tree_handler"

local math_random = math.random
local math_randomseed = math.randomseed
local table_insert = table.insert
local table_remove = table.remove
local table_sort = table.sort
local tostring = tostring

local TASK_CYCLE_DAILY = 1  --日常任务
local TASK_CYCLE_WEEK = 2     --周常任务

local MAIL_COUNT_LIMIT = 50

local FLAGS_NEWBIE_AWARD = 0x1  --领取过新手礼物
local FLAGS_BIND_PHONE_AWARD = 0x2 --领取过绑定手机奖励
local reset_tree_task = tree_handler.reset_tree_task

local meta = {}

local meta_index = {}
meta.__index = meta_index

function meta.new(uid,user_data)
    local o = {
        uid = uid,
        user_data = user_data,
    }
    return setmetatable(o, meta)
end

function meta_index:billlog(op,params)
    params['device_brand'] = self.device_brand
    params['device_id'] = self.device_id
    params['uid'] = self.uid
    params['op'] = op
    params['channel'] = self.user_data.channel
    params['cur_channel'] = self.cur_channel
    params['client_version'] = self.client_version
    params['ip'] = params.ip or self.ip
    params['os_system'] = self.user_data.os_system
    params['platform'] = self.user_data.platform
    billlog(params)
end

function meta_index:get_extra_bill_info()
    local t = {}
    t.client_version =  self.client_version
    t.channel = self.user_data.channel
    t.cur_channel = self.cur_channel
    t.device_id = self.device_id
    t.device_brand = self.device_brand
    t.os_system = self.user_data.os_system
    t.platform = self.user_data.platform
    t.current_system = self.os_system
    return t
end

--------------------------------------------------

local function trunc_name(user_info)
    local name_map = user_info.name_map
    local total_len = 0
    for _,wlen in pairs(name_map) do
        if wlen == 1 then
            total_len = total_len + 1
        else
            total_len = total_len + 2
        end
    end

    if total_len <= 10 then return end

    local offset = 0
    local name_length = 0
    for _,wlen in pairs(name_map) do
        local length = 2
        if wlen == 1 then
            length = 1
        end

        if name_length + length > 10 then
            break
        end

        name_length = name_length + length
        offset = offset + wlen
    end
    user_info.name = user_info.name:sub(1,offset)
end

--获取默认头像框为vip0级头像框
local function get_default_icon_border()
    for _,v in pairs(global_configs.vip) do
        if v.level == 0 then
            return v.icon_border_url
        end
    end

    return ''
end

function meta_index:check_user_data(result,msg)
    local is_new_player = false
    local user_data = self.user_data
    if not user_data.sign_info then
        local sign_info = user_data:new_table_field('sign_info')
        sign_info.last_time = 0
        sign_info.days = 0
    end

    if not user_data.name then
        is_new_player = true
        if result.user_info and result.user_info.name then
            trunc_name(result.user_info)
            user_data.name = result.user_info.name
        else
            local names_library = global_configs.names_library
            --名字开始默认和id一样
            user_data.name = tostring(self.uid) --names_library[math_random(1,#names_library)]
        end
    end

    if not user_data.sex then
        user_data.sex = (result.user_info and result.user_info.sex) or math_random(1,2)
    end

    if user_data.icon then
        if result.user_info and result.user_info.icon and 
            result.user_info.icon ~= user_data.icon then
            user_data.icon = result.user_info.icon
        elseif user_data.icon == '' then
            user_data.icon = tostring(user_data.sex)
        end
    elseif result.user_info and result.user_info.icon then
        user_data.icon = result.user_info.icon
    else
        user_data.icon = tostring(user_data.sex)
    end

    --新增平台标记
    if not user_data.platform then
        user_data.platform = msg.platform
    end

    --新增用户首次注册的系统类型
    if not user_data.os_system then
        user_data.os_system = msg.os_system
    end

    --注册包渠道
    if not user_data.channel and msg.channel then
        user_data.channel = msg.channel:lower()
    end

    if not user_data.level then
        user_data.level = 0
    end

    if not user_data.play_total_count then
        user_data.play_total_count = 0
    end

    if not user_data.play_win_count then
        user_data.play_win_count = 0
    end

    if not user_data.last_check_day_time then
        user_data.last_check_day_time = 0
    end

    if not user_data.jiabei_card then
        user_data.jiabei_card = 0
    end

    if not user_data.last_login_time then
        user_data.last_login_time = 0
    end

    if not user_data.last_login_ip then
        user_data.last_login_ip = 0
    end

    if not user_data.flags then
        user_data.flags = 0
    end

    if not user_data.phone_code then
        user_data.phone_code = ''
    end

    if not user_data.register_machine then
        user_data.register_machine = ''
    end

    if not user_data.register_ip then
        user_data.register_ip = ''
    end

    if not user_data.line_status then
        user_data.line_status = false
    end

    if not user_data.user_guide_time then
        user_data.user_guide_time = 0
    end

    if not user_data.user_guide_gm_time then
        user_data.user_guide_gm_time = 0
    end

    if not user_data.icon_border then
        user_data.icon_border = get_default_icon_border()
    end
    if not user_data.award_count then
        user_data.award_count = 0
    end
    if not user_data.add_vip_count then
        user_data.add_vip_count = 0
    end
    if not user_data.add_login_day then
        user_data.add_login_day = 0
    end

    if not user_data.task_info then                 --任务存储结构：task_info{daily_task_list{task_type:{{task_id,process,status}}}}
        local task_info = user_data:new_table_field('task_info')
        task_info:new_table_field('process_list')
        task_info:new_table_field('taken_list')
    end

    if not user_data.mail_info then
        local mail_info = user_data:new_table_field('mail_info')
        mail_info.mail_seq = 0
        mail_info:new_table_field('mail_list')
    end

    if not user_data.guns_list then
        user_data:new_table_field('guns_list')
    end

    if not user_data.guide_flag then
        user_data.guide_flag = constant.GUIDE_FLAG_NO
    end

    if not user_data.has_changed_name then
        user_data.has_changed_name = false
    end

    if not user_data.vip_award_info then  --vip奖励存储结构：vip_award_info{{vip_level,status}}
        user_data:new_table_field('vip_award_info')
    end

    if not user_data.welfare_sign_info then  --福利中心签到存储结构：
        user_data:new_table_field('welfare_sign_info')
        user_data.welfare_sign_info.sign_count = 0  --当月累计签到次数
        
        user_data.welfare_sign_info.sign_state = 0 --每日签到状态
        user_data.welfare_sign_info.month_state = 0 --当月领取状态
        user_data.welfare_sign_info.month_water = 0 --当月流水
        user_data.welfare_sign_info.month_salary = 0 --月俸禄
    end 

    --摇钱树
    if not user_data.tree_info then
        user_data:new_table_field('tree_info')
        user_data.tree_info:new_table_field('task_info')
        user_data.tree_info:new_table_field('records')
        user_data.tree_info.level = 1
        user_data.tree_info.exp = 0
        xpcall(reset_tree_task,debug.traceback,user_data.tree_info)
    end

    --视讯渠道名 AG BG 
    if not user_data.shisun_platform then 
        user_data.shisun_platform = ""
    end    
    --当前所在视讯游戏
    if not user_data.shisun_table_type then 
        user_data.shisun_table_type = 0
    end

    return is_new_player
end

--增加头像框 data = {url = 头像框url,end_time = 结束时间戳} end_time=-1 代表永久头像框
function meta_index:open_icon_border(icon_border)
    if not icon_border then
        return
    end

    local icon_border_list = self.user_data.icon_border_list
    if not icon_border_list then
        return
    end
    
    local found = icon_border_list:new_table_field(#icon_border_list + 1)
    found.url = icon_border.url
    found.end_time = icon_border.end_time
end

--增加炮台
function meta_index:add_guns_list(guns_info)
    if not guns_info then
        return
    end

    local guns_list = self.user_data.guns_list
    if not guns_list then
        return
    end

    local found = guns_list:new_table_field(#guns_list + 1)
    found.end_time = guns_info.end_time or 0  --到期时间
    found.id = guns_info.id
end

function meta_index:check_vip_open_action(vip_level)
    -- 添加捕鱼炮台
    local guns_id_map = {}
    for _,info in pairs(self.user_data.guns_list) do
        guns_id_map[info.id] = true
    end
    for _,data in pairs(global_configs.fishing_guns) do
        if vip_level >=  data.vip_level and not guns_id_map[data.id] then
            self:add_guns_list({id = data.id,end_time = 0})
            R().basesvr{key=self.uid}:send('.msg_handler','set_fish_gun',self.uid,data.id,true)
        end
    end

    print("check_vip_icon_border============222",tostring_r(self.user_data.guns_list))
end
-------------------------------------------------------
local function new_mail_seq(mail_info)
	local mail_seq = mail_info.mail_seq
	if mail_seq >= 2000000000 then
		mail_info.mail_seq =  1
	else
		mail_info.mail_seq = mail_seq + 1 --新邮件必须保证先加seq
	end

	return mail_seq
end

local function get_list_count(data_list)
    local count = 0
    for k,v in pairs(data_list) do
        count = count + 1
    end
    return count
end

--删除最老的邮件
local function delete_oldest_mail(mail_list)
	local count = get_list_count(mail_list)
	local oldest_time = 0
	local oldest_seq = -1
	for seq,mail_obj in pairs(mail_list) do
		if oldest_time == 0 then
			oldest_time = mail_obj.send_time
			oldest_seq = seq
		end
		local mail_info_send_time = mail_obj.send_time
		if mail_info_send_time < oldest_time then
			oldest_time = mail_info_send_time
			oldest_seq = seq
		end
	end
    mail_list:delete_from_hash(tostring(oldest_seq))
	return true
end

function meta_index:add_mail(mail_id,param1,param2,attach_list)
    local user_data = self.user_data
    local mail_info = user_data.mail_info
    local mail_list = mail_info.mail_list

    local mail_seq = new_mail_seq(mail_info)
    
    --检查邮件是否超出限制
    local count = get_list_count(mail_list)
    if count >= MAIL_COUNT_LIMIT then
        delete_oldest_mail(mail_list)
    end

    local one_mail = mail_list:new_table_field(tostring(mail_seq))

    one_mail.mail_seq = mail_seq
    one_mail.mail_id = mail_id
    if param1 then one_mail.param1 = param1 end
    if param2 then one_mail.param2 = param2 end
    
    if attach_list then
        local mail_attach_list = one_mail:new_table_field('attach_list')
        for id,count in pairs(attach_list) do
            local attach_info = mail_attach_list:new_table_field(#mail_attach_list + 1)
            attach_info.id = id
            attach_info.count = count
        end
    end

    return true
end

local function rand_from_table(count,tb)
    local selected = {}
    
    math_random(0,#tb)
    --math_randomseed(util.get_now_time())
    if count >= #tb then
        return tb
    end
    while #selected < count do
        math_random(1,#tb)
        table_insert(selected,table_remove(tb,math_random(1,#tb)))
    end
    return selected
end

local function reset_task(player,cycle,task)
    local user_data = player.user_data
    local task_info = user_data.task_info
    user_data.welfare_sign_info.sign_state = 0 --每日签到状态
        
    task_info:delete_from_hash('process_list')
    task_info:delete_from_hash('taken_list')

    task_info:new_table_field('process_list')
    task_info:new_table_field('taken_list')
end

local function check_and_cross_day(player,curr_time)
    --任务重置
    local user_data = player.user_data
    if util.is_same_day(curr_time,user_data.last_check_day_time) then
       return false
    end
    dbglog("check_and_cross_day")
    --任务跨天
    local ok,msg = pcall(reset_task,player,TASK_CYCLE_DAILY,global_configs.task)
    if not ok then errlog(msg) end

    local ok,msg = pcall(reset_tree_task,user_data.tree_info)
    if not ok then errlog(msg) end

    -- -- 通知base 做夸天操作
    R().basesvr(1):send('.msg_handler','player_cross_day',player.uid)
    --签到跨天
    return true
end

--跨下午三点
local function check_cross_sunup_day(player,curr_time)
    local user_data = player.user_data
    --dbglog(last_time,curr_time,util.is_same_sunup_day(user_data.last_check_day_time,curr_time,15))
    if util.is_same_sunup_day(user_data.last_check_day_time,curr_time,15) then
        return false
    end
    -- 通知base 做夸天操作
    R().basesvr(1):send('.msg_handler','player_cross_time',player.uid)
    return true
end

local function check_and_cross_week(player,curr_time)
    local user_data = player.user_data
    if util.is_same_week(curr_time,user_data.last_check_day_time) then
        return false
    end

    return true
end

local function reset_salary_info(player)
    local user_data = player.user_data
    user_data.welfare_sign_info.sign_count = 0  --当月累计签到次数
    user_data.welfare_sign_info.month_state = 0 --当月领取状态
    user_data.welfare_sign_info.month_water = 0 --当月流水
end

local function check_and_cross_month(player,curr_time)
    local user_data = player.user_data
    if util.is_same_month(curr_time,user_data.last_check_day_time) then
        return false
    end

    --任务跨天
    local ok,msg = pcall(reset_salary_info,player)
    if not ok then errlog(msg) end

    return true
end

--检查是否跨天
local function check_time_cross(player,ntf)
    local curr_time = util.get_now_time() + player.diff_time
    local cross_day = check_and_cross_day(player,curr_time)
    check_and_cross_week(player,curr_time)
    check_and_cross_month(player,curr_time)
    check_cross_sunup_day(player,curr_time)
    player.user_data.last_check_day_time = curr_time

    return cross_day
end

meta_index.check_time_cross = check_time_cross

local function on_player_online_check()
    local uid = player.uid
    local personal_control = global_configs.personal_control or {}
    local online_check = personal_control['online_check']
    if not online_check then
        errlog("on_player_exchange==",uid)
        return
    end

    -- local args = {
    --     not_control_rate = common_contorl.not_control_rate or 0,
    --     control_win_list  = common_contorl.control_rate or {},
    --     control_lose_list = common_contorl.control_rate_lose or {},
    --     random_rate = math_random(online_check.rate_min or 0,online_check.rate_max or 0),
    -- }
    --{control_value = 0,win_rate = 0,lose_rate = 0}
    local ok,ret_data = R().basesvr{key=uid}:call('.msg_handler','get_online_control',uid)
    print("on_player_online_check====0000",uid,ok,tostring_r(ret_data))
    if not ok or not ret_data then
        return
    end

    local control_value = ret_data.control_value or 0
    if control_value == 0 then
        return
    end

    local control_data = {
        control_coins = control_value,
        win_rate = ret_data.win_rate,
        lose_rate = ret_data.lose_rate,
        weight = online_check.weight,
        xiaoR_level = personal_control.xiaoR_level or 1000000,
        add_type = 1, --表示在线检测
        online_lose = ret_data.online_lose,
    }
    print("on_player_online_check====2222",uid,control_value)

    R().basesvr({key=uid}):send('.msg_handler','add_player_personal_control',uid,control_data)
end

local function check_player_control(player)
    local online_check = global_configs.personal_control.online_check
    print("check_player_control====",online_check)
    if not online_check then
        return
    end   
    local random_time = math_random(online_check.time_min or 0,online_check.time_max or 0)
    local now = util.get_now_time()
    print("check_player_control===============",player.uid, random_time, now - player.last_check_control_time)
    if random_time > 0 and now - player.last_check_control_time >= random_time then
        on_player_online_check()
        player.last_check_control_time = now
    end
end
meta_index.check_player_control = check_player_control

function meta_index:add_paid_product(payment)
    local curr_uid = self.uid
    --在这里为玩家进行发货处理
    print(tostring_r(payment))

    local goods_id = payment.product_id
    local goods_conf = global_configs.shop[goods_id]
    if not goods_conf then
        errlog('could not find goods_id',goods_id)
        return
    end

    --判断下价格是否满足
    assert(goods_conf.price.currency == constant.ITEM_RMB_ID)
    local required_amount = goods_conf.price.amount
    if required_amount > goods_conf.price.amount then
        errlog(curr_uid,'not enough amount to pay',required_amount,goods_conf.price.amount,goods_id)
        self:billlog('rmbbuy',{goods_id = goods_id,amount = required_amount,success = false})
        return
    end

    local reason = 0
    --钱够了，则给加上道具
    local goods = goods_conf.goods
    if not self:can_add_item(goods.item_id,goods.item_count,reason) then
        errlog(curr_uid,'can not add item',goods.item_id,goods.item_count)
        return
    end

    print(curr_uid,'now add item',goods.item_id,goods.item_count)
    self:add_item(goods.item_id,goods.item_count,reason)

    self:billlog('rmbbuy',{goods_id = goods_id,amount = required_amount,success = true})

    return true
end

function meta_index:can_take_newbie_award()
    local taken = self.user_data.flags & FLAGS_NEWBIE_AWARD
    return taken == 0
end

function meta_index:set_newbie_award()
    self.user_data.flags = self.user_data.flags | FLAGS_NEWBIE_AWARD
    return true
end

function meta_index:can_take_bind_phone_award()
    local taken = self.user_data.flags & FLAGS_BIND_PHONE_AWARD
    return taken == 0
end

function meta_index:set_bind_phone_award()
    if (self.user_data.flags & FLAGS_BIND_PHONE_AWARD) ~= 0 then return false end
    self.user_data.flags = self.user_data.flags | FLAGS_BIND_PHONE_AWARD
    return true
end


local function TASK_TYPE_FINISH_GAMES_FUNC(one_task_cfg,process_info)
    if not process_info then
        return 0
    end
    local game_type = one_task_cfg.game_type
    for _,game_info in pairs(process_info.games) do
        if game_info.type == game_type then
            return game_info.times
        end
    end

    return 0
end

local function TASK_TYPE_WIN_GAMES_FUNC(one_task_cfg,process_info)
    if not process_info then
        return 0
    end
    local game_type = one_task_cfg.game_type
    for _,game_info in pairs(process_info.games) do
        if game_info.type == game_type then
            return game_info.times
        end
    end

    return 0
end

local function make_got_paixing_type(game_type,card_type)
    return game_type << 10 | card_type
end

local function TASK_TYPE_GOT_PAIXING_FUNC(one_task_cfg,process_info)
    if not process_info then
        return 0
    end
    local game_type = one_task_cfg.game_type
    local card_type = one_task_cfg.param

    local mix_type = make_got_paixing_type(game_type,card_type)
    for _,game_info in pairs(process_info.games) do
        if game_info.type == mix_type then
            return game_info.times
        end
    end

    return 0
end

local function TASK_TYPE_SHARE_FUNC(one_task_cfg,process_info)
    if not process_info then
        return 0
    end

    return process_info.times or 0
end


local TASK_TYPE_DEF = constant.TASK_TYPE_DEF
local TASK_TYPE_HANDLER = {
    [TASK_TYPE_DEF.TASK_TYPE_FINISH_GAMES] = TASK_TYPE_FINISH_GAMES_FUNC,
    [TASK_TYPE_DEF.TASK_TYPE_WIN_GAMES] = TASK_TYPE_WIN_GAMES_FUNC,
    [TASK_TYPE_DEF.TASK_TYPE_GOT_PAIXING] = TASK_TYPE_GOT_PAIXING_FUNC,
    [TASK_TYPE_DEF.TASK_TYPE_SHARE] = TASK_TYPE_SHARE_FUNC,
}

function meta_index:check_task_process(task_type)
    local user_data = self.user_data
    local task_info = user_data.task_info

    local process_list = task_info.process_list
    local process_info
    for _,pi in pairs(process_list) do
        if pi.type == task_type then
            process_info = pi
            break
        end
    end

    local taken_list = task_info.taken_list
    local taken_map = {}
    for _,task_id in pairs(taken_list) do
        taken_map[task_id] = true
    end

    local task_cfg = global_configs.task
    for task_id,one_task_cfg in pairs(task_cfg) do
        if taken_map[task_id] then
            goto continue
        end

        if one_task_cfg.type ~= task_type then
            goto continue
        end

        local task_func = assert(TASK_TYPE_HANDLER[task_type],task_type)
        local curr_process = task_func(one_task_cfg,process_info)
        local process_limit = one_task_cfg.process
        if curr_process >= process_limit then
            return true
        end
        
        ::continue::
    end

    return false
end

local TASK_BTN_STATUS_FORWARD = 0   --前往
local TASK_BTN_STATUS_SHARE = 10   --分享
local TASK_BTN_STATUS_TAKE = 20   --领取

local function task_cmp(a,b)
    if a.btn_status ~= b.btn_status then
        return a.btn_status > b.btn_status
    end

    return a.task_id < b.task_id
end

function meta_index:make_task_list()
    local user_data = self.user_data
    local task_info = user_data.task_info

    local process_list = task_info.process_list
    local process_map = {}
    for _,process_info in pairs(process_list) do
        process_map[process_info.type] = process_info
    end

    local taken_list = task_info.taken_list
    local taken_map = {}
    for _,task_id in pairs(taken_list) do
        taken_map[task_id] = true
    end
    
    local task_share_type = constant.TASK_TYPE_DEF.TASK_TYPE_SHARE
    local rsp_task_list = {}
    local task_cfg = global_configs.task
    for task_id,one_task_cfg in pairs(task_cfg) do
        local task_type = one_task_cfg.type
        if taken_map[task_id] and 
            task_type ~= task_share_type then
            --这个任务已经领取过了
            goto continue
        end

        local process_limit = one_task_cfg.process

        local task_func = assert(TASK_TYPE_HANDLER[task_type],task_type)
        local curr_process = task_func(one_task_cfg,process_map[task_type])
        if curr_process > process_limit then
            curr_process = process_limit
        end
        
        local award_list = {}
        for _,award_cfg in pairs(one_task_cfg.award_list) do
            table_insert(award_list,{
                id = award_cfg.id,
                count = award_cfg.count
            })
        end

        local btn_status = TASK_BTN_STATUS_FORWARD
        if curr_process >= process_limit then
            btn_status = TASK_BTN_STATUS_TAKE
        end

        if task_type == task_share_type then
            if taken_map[task_id] or btn_status ~= TASK_BTN_STATUS_TAKE then
                btn_status = TASK_BTN_STATUS_SHARE
            end
        end

        local rsp_task = {
            task_id = task_id,
            name = one_task_cfg.name,
            process_limit = process_limit,
            process = curr_process,
            award_list = award_list,
            game_type = one_task_cfg.game_type,
            btn_status = btn_status,
        }

        table_insert(rsp_task_list,rsp_task)
        ::continue::
    end

    table_sort(rsp_task_list,task_cmp)

    return rsp_task_list
end


function meta_index:take_task_award(task_id)
    local task_cfg = global_configs.task
    local one_task_cfg = task_cfg[task_id]
    if not one_task_cfg then
        return false,-3333
    end

    local user_data = self.user_data
    local task_info = user_data.task_info
    local task_type = one_task_cfg.type

    local process_list = task_info.process_list
    local process_info
    for _,pi in pairs(process_list) do
        if pi.type == task_type then
            process_info = pi
            break
        end
    end

    local taken_list = task_info.taken_list
    for _,tmp_task_id in pairs(taken_list) do
        --已经领取过了
        if tmp_task_id == task_id then
            return false,error_code.TASK_AWARD_HAVE_BEEN_TAKEN
        end
    end
    
    --判断下进度
    local task_func = assert(TASK_TYPE_HANDLER[task_type],task_type)
    local curr_process = task_func(one_task_cfg,process_info)
    if curr_process < one_task_cfg.process then
        return false,error_code.TASK_UNCOMPLETED
    end

    --记为已领取
    taken_list[#taken_list + 1] = task_id

    return true,one_task_cfg.award_list
end

function meta_index:update_game_process(task_type,game_type,process)
    local task_cfg = global_configs.task
    local found
    for _,one_task_cfg in pairs(task_cfg) do
        if one_task_cfg.type == task_type and 
            one_task_cfg.game_type == game_type then
            found = true
        end
    end

    if not found then
        return false
    end

    local user_data = self.user_data
    local task_info = user_data.task_info

    local process_list = task_info.process_list
    local found
    for _,process_info in pairs(process_list) do
        if process_info.type == task_type then
            found = process_info
            break
        end
    end

    if not found then
        found = process_list:new_table_field(#process_list + 1)
        found.type = task_type
        found:new_table_field('games')
    end

    local games = found.games

    local found_game_info
    for _,game_info in pairs(games) do
        if game_info.type == game_type then
            found_game_info = game_info
            break
        end
    end
    
    if not found_game_info then
        found_game_info = games:new_table_field(#games + 1)
        found_game_info.type = game_type
        found_game_info.times = 0
    end

    found_game_info.times = found_game_info.times + process

    return true
end

function meta_index:update_card_type_process(game_type,card_type,process)
    local task_type = constant.TASK_TYPE_DEF.TASK_TYPE_GOT_PAIXING
    local task_cfg = global_configs.task
    local found
    for _,one_task_cfg in pairs(task_cfg) do
        if one_task_cfg.type == task_type and 
            one_task_cfg.game_type == game_type and
            one_task_cfg.param == card_type then
            found = true
        end
    end

    if not found then
        return false
    end

    local user_data = self.user_data
    local task_info = user_data.task_info

    local process_list = task_info.process_list
    local found
    for _,process_info in pairs(process_list) do
        if process_info.type == task_type then
            found = process_info
            break
        end
    end

    if not found then
        found = process_list:new_table_field(#process_list + 1)
        found.type = task_type
        found:new_table_field('games')
    end

    local games = found.games

    local mix_type = make_got_paixing_type(game_type,card_type)
    local found_game_info
    for _,game_info in pairs(games) do
        if game_info.type == mix_type then
            found_game_info = game_info
            break
        end
    end
    if not found_game_info then
        found_game_info = games:new_table_field(#games + 1)
        found_game_info.type = mix_type
        found_game_info.times = 0
    end

    found_game_info.times = found_game_info.times + (process or 1)

    return true
end

function meta_index:update_share_progress(process)
    local task_type = constant.TASK_TYPE_DEF.TASK_TYPE_SHARE
    local task_cfg = global_configs.task
    local found
    for _,one_task_cfg in pairs(task_cfg) do
        if one_task_cfg.type == task_type then
            found = true
        end
    end

    if not found then
        return false
    end

    local user_data = self.user_data
    local task_info = user_data.task_info

    local process_list = task_info.process_list
    local found
    for _,process_info in pairs(process_list) do
        if process_info.type == task_type then
            found = process_info
            break
        end
    end

    if not found then
        found = process_list:new_table_field(#process_list + 1)
        found.type = task_type
        found.times = 0
    end

    found.times = found.times + (process or 1)

    return true
end

return meta